﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using YArchitech.Revit.RevitExtension;

namespace Model
{
	public class HYCableTrayConduitRoundBeam
	{
		public bool CableTrayConduitRoundBeam(IList<MEPCurve> mepCurves, IList<XYZ> xyzs, double offSet, double angle, RoundBeamType type)
		{
			double num = 20.0;
			bool result;
			try
			{
				CableTrayConduitBase cableTrayConduitBase = mepCurves[0] as CableTrayConduitBase;
				double num2 = RoundBeanEntity.GetHeightOrDiameter(cableTrayConduitBase) / 2.0;
				double num3 = RoundBeanEntity.GetWidthOrDiameter(cableTrayConduitBase) / 2.0;
				MEPCurve mepCurve = mepCurves[1];
				double num4 = RoundBeanEntity.GetHeightOrDiameter(mepCurve) / 2.0;
				double num5 = RoundBeanEntity.GetWidthOrDiameter(mepCurve) / 2.0;
				Document document = cableTrayConduitBase.Document;
				HYCableTray<CableTrayConduitBase> hycableTray = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase);
				ElementId elementId = cableTrayConduitBase.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId();
				ElementId typeId = hycableTray.CableTray.GetTypeId();
				XYZ xyz = hycableTray.CustomConnectorStart.XYZ;
				XYZ xyz2 = hycableTray.CustomConnectorEnd.XYZ;
				XYZ xyz3 = hycableTray.GetGlobalOnCenterLinePoint(xyzs[0]);
				XYZ xyz4 = hycableTray.GetGlobalOnCenterLinePoint(xyzs[1]);
				XYZ xyz5 = (xyz4 - xyz3).Normalize();
				this.topVector = xyz5;
				XYZ xyz6 = new XYZ();
				XYZ xyz7 = new XYZ();
				double leastOffset = RoundBeanEntity.GetLeastOffset(document, cableTrayConduitBase, type, angle);
				if (Math.Abs(offSet) <= leastOffset)
				{
					offSet = leastOffset + AssistFunc.mmToFeet(20.0) * Math.Sin(angle);
				}
				else if (type == RoundBeamType.Lift)
				{
					offSet = offSet + num2 + num4;
				}
				else if (RoundBeanEntity.ConfirmRefMEPCurveSize(cableTrayConduitBase, mepCurve))
				{
					offSet = offSet + num3 + num4;
				}
				else
				{
					offSet = offSet + num3 + num5;
				}
				double num6 = 0.0;
				double num7 = Math.Tan(angle);
				if (num7 < 0.0001)
				{
					num7 = 0.0;
				}
				if (0.0 != num7)
				{
					num6 = Math.Abs(offSet / num7);
				}
				if (Math.Abs(num6) < 0.0001)
				{
					num6 = 0.0;
				}
				if (type == RoundBeamType.Lift)
				{
					xyz6 = xyz3 - xyz5 * num6;
					xyz7 = xyz4 + xyz5 * num6;
					xyz3 += offSet * XYZ.BasisZ;
					xyz4 += offSet * XYZ.BasisZ;
				}
				else if (type == RoundBeamType.Offset)
				{
					XYZ lineProject = hycableTray.GetLineProject(xyzs[2]);
					XYZ xyz8 = (new XYZ(xyzs[2].X, xyzs[2].Y, lineProject.Z) - lineProject).Normalize();
					xyz6 = xyz3 - xyz5 * num6;
					xyz7 = xyz4 + xyz5 * num6;
					xyz3 += offSet * xyz8;
					xyz4 += offSet * xyz8;
				}
				IList<CableTrayConduitBase> list = hycableTray.Separate(xyz6);
				document.Regenerate();
				HYCableTray<CableTrayConduitBase> hycableTray2;
				HYCableTray<CableTrayConduitBase> hycableTray3;
				HYCableTray<CableTrayConduitBase> hycableTray4;
				if (hycableTray.IsPointOnCableTrayCurve(xyz7))
				{
					hycableTray2 = new HYCableTray<CableTrayConduitBase>(list[1]);
					IList<CableTrayConduitBase> list2 = hycableTray.Separate(xyz7);
					document.Regenerate();
					if (hycableTray.CustomConnectorStart.XYZ.IsAlmostEqualTo(xyz) || hycableTray.CustomConnectorStart.XYZ.IsAlmostEqualTo(xyz2) || hycableTray.CustomConnectorEnd.XYZ.IsAlmostEqualTo(xyz) || hycableTray.CustomConnectorEnd.XYZ.IsAlmostEqualTo(xyz2))
					{
						hycableTray3 = new HYCableTray<CableTrayConduitBase>(list2[0]);
						hycableTray4 = new HYCableTray<CableTrayConduitBase>(list2[1]);
					}
					else
					{
						hycableTray3 = new HYCableTray<CableTrayConduitBase>(list2[1]);
						hycableTray4 = new HYCableTray<CableTrayConduitBase>(list2[0]);
					}
				}
				else
				{
					HYCableTray<CableTrayConduitBase> hycableTray5 = new HYCableTray<CableTrayConduitBase>(list[1]);
					hycableTray2 = new HYCableTray<CableTrayConduitBase>(list[0]);
					IList<CableTrayConduitBase> list3 = hycableTray5.Separate(xyz7);
					document.Regenerate();
					if (hycableTray5.CustomConnectorStart.XYZ.IsAlmostEqualTo(xyz) || hycableTray5.CustomConnectorStart.XYZ.IsAlmostEqualTo(xyz2) || hycableTray5.CustomConnectorEnd.XYZ.IsAlmostEqualTo(xyz) || hycableTray5.CustomConnectorEnd.XYZ.IsAlmostEqualTo(xyz2))
					{
						hycableTray3 = new HYCableTray<CableTrayConduitBase>(list3[0]);
						hycableTray4 = new HYCableTray<CableTrayConduitBase>(list3[1]);
					}
					else
					{
						hycableTray3 = new HYCableTray<CableTrayConduitBase>(list3[1]);
						hycableTray4 = new HYCableTray<CableTrayConduitBase>(list3[0]);
					}
				}
				document.DeleteElement(hycableTray4.CableTray);
				document.Regenerate();
				XYZ xyz9 = (xyz6 - xyz3).Normalize();
				XYZ xyz10 = (xyz7 - xyz4).Normalize();
				CableTrayConduitBase cableTrayConduitBase2;
				CableTrayConduitBase cableTrayConduitBase3;
				CableTrayConduitBase cableTrayConduitBase4;
				if (cableTrayConduitBase is Conduit)
				{
					cableTrayConduitBase2 = Conduit.Create(document, typeId, xyz3, xyz6 + xyz9 * num, elementId);
					cableTrayConduitBase3 = Conduit.Create(document, typeId, xyz4, xyz7 + xyz10 * num, elementId);
					cableTrayConduitBase4 = Conduit.Create(document, typeId, xyz3, xyz4, elementId);
				}
				else
				{
					cableTrayConduitBase2 = CableTray.Create(document, typeId, xyz3, xyz6 + xyz9 * num, elementId);
					cableTrayConduitBase3 = CableTray.Create(document, typeId, xyz4, xyz7 + xyz10 * num, elementId);
					cableTrayConduitBase4 = CableTray.Create(document, typeId, xyz3, xyz4, elementId);
				}
				this.ParameterConvert(hycableTray2.CableTray, cableTrayConduitBase2, document);
				this.ParameterConvert(hycableTray2.CableTray, cableTrayConduitBase4, document);
				this.ParameterConvert(hycableTray2.CableTray, cableTrayConduitBase3, document);
				document.Regenerate();
				XYZ startXYZ = xyz3;
				XYZ endXYZ = xyz6 + xyz9 * num;
				XYZ startXYZ2 = xyz4;
				XYZ endXYZ2 = xyz7 + xyz10 * num;
				HYCableTray<CableTrayConduitBase> hycableTray6 = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase2);
				hycableTray6.StartXYZ = startXYZ;
				hycableTray6.EndXYZ = endXYZ;
				HYCableTray<CableTrayConduitBase> hycableTray7 = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase4);
				HYCableTray<CableTrayConduitBase> hycableTray8 = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase3);
				hycableTray8.StartXYZ = startXYZ2;
				hycableTray8.EndXYZ = endXYZ2;
				if (hycableTray6.IsZAxis() && hycableTray7.IsXAxis())
				{
					hycableTray6.Rotate90();
					hycableTray8.Rotate90();
				}
				else if (hycableTray6.IsZAxis() && !hycableTray7.IsYAxis())
				{
					double xaxisAngle = hycableTray7.GetXAxisAngle();
					hycableTray6.Rotate(Math.PI*.5 - xaxisAngle);
					hycableTray8.Rotate(Math.PI*.5 - xaxisAngle);
				}
				if (hycableTray6.IsZAxis())
				{
					IList<Connector> appropriateConnector = hycableTray6.GetAppropriateConnector(hycableTray7.CableTray);
					if (appropriateConnector != null && appropriateConnector.Count > 1 && appropriateConnector[0].CoordinateSystem.BasisY.IsAlmostEqualTo(appropriateConnector[1].CoordinateSystem.BasisZ))
					{
						hycableTray6.Rotate(Math.PI);
					}
					IList<Connector> appropriateConnector2 = hycableTray8.GetAppropriateConnector(hycableTray7.CableTray);
					if (appropriateConnector2 != null && appropriateConnector2.Count > 1 && appropriateConnector2[0].CoordinateSystem.BasisY.IsAlmostEqualTo(appropriateConnector2[1].CoordinateSystem.BasisZ))
					{
						hycableTray8.Rotate(Math.PI);
					}
				}
				document.Regenerate();
				HYConduitConnect hyconduitConnect = new HYConduitConnect();
				(cableTrayConduitBase4.Location as LocationCurve).Curve = Line.CreateBound(xyz3, xyz4 + xyz5 * num);
				FamilyInstance familyInstance;
				if (cableTrayConduitBase is Conduit)
				{
					familyInstance = hyconduitConnect.NewElbowFitting(new List<Conduit>
					{
						(Conduit)cableTrayConduitBase4,
						(Conduit)cableTrayConduitBase2
					});
				}
				else
				{
					familyInstance = this.NewElbowFitting(new List<CableTray>
					{
						(CableTray)cableTrayConduitBase4,
						(CableTray)cableTrayConduitBase2
					});
				}
				document.Regenerate();
				LocationPoint locationPoint = familyInstance.Location as LocationPoint;
				locationPoint.Move(locationPoint.Point + -xyz5 * num - locationPoint.Point);
				Connector connectorByVector = this.GetConnectorByVector(familyInstance, xyz5);
				(cableTrayConduitBase4.Location as LocationCurve).Curve = Line.CreateBound(connectorByVector.Origin, xyz4);
				FamilyInstance familyInstance2 = this.NewElbowFitting(document, cableTrayConduitBase4, cableTrayConduitBase3);
				document.Regenerate();
				(cableTrayConduitBase4.Location as LocationCurve).Curve = Line.CreateBound(xyz3, xyz4);
				Connector connectorByVector2 = this.GetConnectorByVector(familyInstance, xyz5);
				Connector connectorByVector3 = this.GetConnectorByVector(familyInstance2, xyz5);
				familyInstance.Location.Move(xyz3 - connectorByVector2.Origin);
				familyInstance2.Location.Move(xyz4 - connectorByVector3.Origin);
				document.Regenerate();
				HYCableTray<CableTrayConduitBase> hycableTray9 = null;
				HYCableTray<CableTrayConduitBase> hycableTray10 = null;
				XYZ xyz11 = hycableTray2.IntersectionPoint(cableTrayConduitBase2);
				XYZ xyz12 = (cableTrayConduitBase2.Location as LocationCurve).Curve.GetEndPoint(1) - xyz11;
				Connector connector = (hycableTray2.CustomConnectorStart.XYZ.DistanceTo(xyz11) < hycableTray2.CustomConnectorEnd.XYZ.DistanceTo(xyz11)) ? hycableTray2.CustomConnectorStart.Connector : hycableTray2.CustomConnectorEnd.Connector;
				Connector connector2 = (hycableTray3.CustomConnectorStart.XYZ.DistanceTo(xyz11) < hycableTray3.CustomConnectorEnd.XYZ.DistanceTo(xyz11)) ? hycableTray3.CustomConnectorStart.Connector : hycableTray3.CustomConnectorEnd.Connector;
				if (connector.Origin.DistanceTo(xyz11) < connector2.Origin.DistanceTo(xyz11))
				{
					hycableTray9 = new HYCableTray<CableTrayConduitBase>(hycableTray2.CableTray);
					hycableTray10 = new HYCableTray<CableTrayConduitBase>(hycableTray3.CableTray);
				}
				else
				{
					hycableTray9 = new HYCableTray<CableTrayConduitBase>(hycableTray3.CableTray);
					hycableTray10 = new HYCableTray<CableTrayConduitBase>(hycableTray2.CableTray);
				}
				XYZ xyz13 = hycableTray10.IntersectionPoint(cableTrayConduitBase3);
				XYZ xyz14 = (cableTrayConduitBase3.Location as LocationCurve).Curve.GetEndPoint(1) - xyz13;
				if (hycableTray9.CustomConnectorStart.Connector.IsConnected)
				{
					this.DisconnectFromFitting(hycableTray9.CustomConnectorStart.Connector, hycableTray9);
				}
				if (hycableTray9.CustomConnectorEnd.Connector.IsConnected)
				{
					this.DisconnectFromFitting(hycableTray9.CustomConnectorEnd.Connector, hycableTray9);
				}
				if (hycableTray10.CustomConnectorStart.Connector.IsConnected)
				{
					this.DisconnectFromFitting(hycableTray10.CustomConnectorStart.Connector, hycableTray10);
				}
				if (hycableTray10.CustomConnectorEnd.Connector.IsConnected)
				{
					this.DisconnectFromFitting(hycableTray10.CustomConnectorEnd.Connector, hycableTray10);
				}
				(hycableTray9.CableTray.Location as LocationCurve).Move(xyz12);
				(hycableTray10.CableTray.Location as LocationCurve).Move(xyz14);
				document.Regenerate();
				if (cableTrayConduitBase is Conduit)
				{
					this.fitting1 = hyconduitConnect.NewElbowFitting(new List<Conduit>
					{
						(Conduit)hycableTray9.CableTray,
						(Conduit)cableTrayConduitBase2
					});
					this.fitting2 = hyconduitConnect.NewElbowFitting(new List<Conduit>
					{
						(Conduit)hycableTray10.CableTray,
						(Conduit)cableTrayConduitBase3
					});
				}
				else
				{
					this.fitting1 = this.NewElbowFitting(new List<CableTray>
					{
						(CableTray)hycableTray9.CableTray,
						(CableTray)cableTrayConduitBase2
					});
					this.fitting2 = this.NewElbowFitting(new List<CableTray>
					{
						(CableTray)hycableTray10.CableTray,
						(CableTray)cableTrayConduitBase3
					});
				}
				document.Regenerate();
				(hycableTray9.CableTray.Location as LocationCurve).Move(-xyz12);
				(hycableTray10.CableTray.Location as LocationCurve).Move(-xyz14);
				document.Regenerate();
				foreach (CableTrayConduitBase cableTrayConduitBase5 in this.dicConns.Keys)
				{
					List<Connector> list4 = new List<Connector>();
					if (cableTrayConduitBase5.Id.IntegerValue == hycableTray9.CableTray.Id.IntegerValue)
					{
						list4 = RevitUtils.GetCableTrayConnectors(hycableTray9.CableTray);
					}
					else if (cableTrayConduitBase5.Id.IntegerValue == hycableTray10.CableTray.Id.IntegerValue)
					{
						list4 = RevitUtils.GetCableTrayConnectors(hycableTray10.CableTray);
					}
					foreach (Connector connector3 in RevitUtils.GetConduitFittingConnectors(this.dicConns[cableTrayConduitBase5]))
					{
						if (connector3.Origin.IsAlmostEqualTo(list4[0].Origin))
						{
							connector3.ConnectTo(list4[0]);
						}
						else if (connector3.Origin.IsAlmostEqualTo(list4[1].Origin))
						{
							connector3.ConnectTo(list4[1]);
						}
					}
				}
				document.Regenerate();
				result = true;
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		private bool DisconnectFromFitting(Connector hyStartCableTray1Start, HYCableTray<CableTrayConduitBase> hyCableTray)
		{
			Element fittingByConnector = this.GetFittingByConnector(hyStartCableTray1Start);
			if (fittingByConnector != null)
			{
				foreach (Connector connector in RevitUtils.GetConduitFittingConnectors(fittingByConnector))
				{
					Element cableTrayConduitBaseByConnector = this.GetCableTrayConduitBaseByConnector(connector);
					if (cableTrayConduitBaseByConnector != null && cableTrayConduitBaseByConnector.Id.IntegerValue == hyCableTray.CableTray.Id.IntegerValue)
					{
						hyStartCableTray1Start.DisconnectFrom(connector);
						this.dicConns.Add(hyCableTray.CableTray, fittingByConnector);
						return true;
					}
				}
				return false;
			}
			return false;
		}

		public Element GetFittingByConnector(Connector connector)
		{
			Element result = null;
			ConnectorSet allRefs = connector.AllRefs;
			if (allRefs.Size <= 0)
			{
				return result;
			}
			foreach (object obj in allRefs)
			{
				Element owner = ((Connector)obj).Owner;
				if (owner.Category.Id.IntegerValue.ToString() == "OST_ConduitFitting" || owner.Category.Id.IntegerValue.ToString() == "OST_CableTrayFitting")
				{
					result = owner;
				}
			}
			return result;
		}

		public Element GetCableTrayConduitBaseByConnector(Connector connector)
		{
			Element result = null;
			ConnectorSet allRefs = connector.AllRefs;
			if (allRefs.Size <= 0)
			{
				return result;
			}
			foreach (object obj in allRefs)
			{
				Element owner = ((Connector)obj).Owner;
				if (owner is CableTray || owner is Conduit)
				{
					result = owner;
				}
			}
			return result;
		}

		public bool IsPointOnCableTrayCurve(XYZ xyz, CableTrayConduitBase startCableTray)
		{
			bool result = false;
			XYZ hyendPoint = (startCableTray.Location as LocationCurve).Curve.GetEndPoint(0);
			XYZ hyendPoint2 = (startCableTray.Location as LocationCurve).Curve.GetEndPoint(1);
			if (Math.Abs(xyz.DistanceTo(hyendPoint) + xyz.DistanceTo(hyendPoint2) - hyendPoint.DistanceTo(hyendPoint2)) < 0.0001)
			{
				result = true;
			}
			return result;
		}

		public XYZ IntersectionPoint(CableTrayConduitBase cableTray, CableTrayConduitBase cableTrayOther)
		{
			XYZ result = null;
			LocationCurve locationCurve = cableTray.Location as LocationCurve;
			LocationCurve locationCurve2 = cableTrayOther.Location as LocationCurve;
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			Line line = YJKLineEx.YJKGetBound(locationCurve.Curve.GetEndPoint(0), locationCurve.Curve.GetEndPoint(1));
			Curve curve = YJKLineEx.YJKGetBound(locationCurve2.Curve.GetEndPoint(0), locationCurve2.Curve.GetEndPoint(1));
			line.MakeUnbound();
			curve.MakeUnbound();
			SetComparisonResult setComparisonResult = line.Intersect(curve, out intersectionResultArray);
			if (4 != (int)setComparisonResult && intersectionResultArray != null && !intersectionResultArray.IsEmpty)
			{
				result = intersectionResultArray.get_Item(0).XYZPoint;
			}
			return result;
		}

		private Connector GetConnectorByVector(FamilyInstance fi, XYZ vector)
		{
			Connector result = null;
			foreach (Connector connector in RevitUtils.GetConduitFittingConnectors(fi))
			{
				if (connector.CoordinateSystem.BasisZ.Normalize().IsAlmostEqualTo(vector) || connector.CoordinateSystem.BasisZ.Normalize().IsAlmostEqualTo(-vector))
				{
					result = connector;
					break;
				}
			}
			return result;
		}

		private Connector GetOtherConnectorByVector(FamilyInstance fi, XYZ vector)
		{
			Connector result = null;
			foreach (Connector connector in RevitUtils.GetConduitFittingConnectors(fi))
			{
				if (!connector.CoordinateSystem.BasisZ.Normalize().IsAlmostEqualTo(vector) && !connector.CoordinateSystem.BasisZ.Normalize().IsAlmostEqualTo(-vector))
				{
					result = connector;
					break;
				}
			}
			return result;
		}

		public FamilyInstance NewElbowFitting(IList<CableTray> cableTrays)
		{
			FamilyInstance familyInstance = null;
			FamilyInstance result;
			try
			{
				if (cableTrays.Count < 2)
				{
					throw new System.ArgumentNullException("CableTray", "is null");
				}
				Document document = cableTrays[0].Document;
				HYCableTray<CableTray> hycableTray = new HYCableTray<CableTray>(cableTrays[0]);
				HYCableTray<CableTray> hycableTray2 = new HYCableTray<CableTray>(cableTrays[1]);
				XYZ xyz = hycableTray.IntersectionPoint(hycableTray2.CableTray);
				if (xyz != null)
				{
					Connector appropriateConnector = hycableTray.GetAppropriateConnector(xyz);
					Connector appropriateConnector2 = hycableTray2.GetAppropriateConnector(xyz);
					if (appropriateConnector == null || appropriateConnector2 == null || appropriateConnector.IsConnected || appropriateConnector2.IsConnected)
					{
						throw new Exception("桥架已经连接");
					}
					familyInstance = document.Create.NewElbowFitting(appropriateConnector, appropriateConnector2);
				}
				result = familyInstance;
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public FamilyInstance NewElbowFitting(Document doc, CableTrayConduitBase conduit1, CableTrayConduitBase conduit2)
		{
			HYCableTray<CableTrayConduitBase> hycableTray = new HYCableTray<CableTrayConduitBase>(conduit1);
			HYCableTray<CableTrayConduitBase> hycableTray2 = new HYCableTray<CableTrayConduitBase>(conduit2);
			Connector connector = hycableTray.CustomConnectorStart.Connector.IsConnected ? hycableTray.CustomConnectorEnd.Connector : hycableTray.CustomConnectorStart.Connector;
			Connector closeConnector = hycableTray2.GetCloseConnector(connector.Origin);
			return doc.Create.NewElbowFitting(connector, closeConnector);
		}

		private void ParameterConvert(CableTrayConduitBase sourceCableTray, CableTrayConduitBase newCableTray, Document document)
		{
			SubTransaction subTransaction = new SubTransaction(document);
			subTransaction.Start();
			foreach (object obj in newCableTray.Parameters)
			{
				Parameter parameter = (Parameter)obj;
                switch ((int)parameter.StorageType)
				{
				case 1:
					if (!parameter.IsReadOnly)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsInteger());
					}
					break;
				case 2:
					if (parameter.Id.IntegerValue != -1114132 && !parameter.IsReadOnly)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsDouble());
					}
					break;
				case 3:
					if (!parameter.IsReadOnly && parameter.IsShared)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsString());
					}
					break;
				case 4:
					parameter.AsElementId();
					if (!parameter.IsReadOnly)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsElementId());
					}
					break;
				}
			}
            if ((int)subTransaction.Commit() == 5)
			{
				subTransaction.RollBack();
			}
		}

		private FamilyInstance fitting1;

		private FamilyInstance fitting2;

		private XYZ topVector;

		private Dictionary<CableTrayConduitBase, Element> dicConns = new Dictionary<CableTrayConduitBase, Element>();
	}
}
